use crate::handlers::*;

use crate::AppState;
use crate::{CreateChat, UpdateChat};
use axum::Router;
use chat_core::error::ErrorOutput;
use chat_core::SigninUser;
use chat_core::SignupUser;
use chat_core::{Chat, ChatType, CreateMessages, Messages, User, Workspace};
use utoipa::{
    openapi::{
        self,
        security::{HttpAuthScheme, HttpBuilder, SecurityScheme},
    },
    Modify, OpenApi,
};
use utoipa_rapidoc::RapiDoc;
use utoipa_redoc::{Redoc, Servable};
use utoipa_swagger_ui::SwaggerUi;
pub(crate) trait OpenApiRouter {
    fn openapi(self) -> Self;
}
#[derive(OpenApi)]
#[openapi(
   components(schemas(
    Chat,ChatType,User,Messages,CreateMessages,Workspace,CreateChat,UpdateChat,SigninUser,SignupUser,ErrorOutput
    ,AuthOutput
   )),
   paths(signup_handler, signin_handler),
   tags(
    (name = "todo", description = "Todo items management API")),
  info(
    title = "Chat Server",
    version = "1.0.0",
    description = "Chat Server API",
))]
pub(crate) struct ApiDoc;

#[allow(dead_code)]
struct SecurityAddon;

impl Modify for SecurityAddon {
    fn modify(&self, openapi: &mut openapi::OpenApi) {
        if let Some(components) = openapi.components.as_mut() {
            components.add_security_scheme(
                "token",
                SecurityScheme::Http(HttpBuilder::new().scheme(HttpAuthScheme::Bearer).build()),
            );
        }
    }
}

impl OpenApiRouter for Router<AppState> {
    fn openapi(self) -> Self {
        self.merge(SwaggerUi::new("/swagger-ui").url("/api-docs/openapi.json", ApiDoc::openapi()))
            .merge(Redoc::with_url("/redoc", ApiDoc::openapi()))
            .merge(RapiDoc::new("/api-docs/openapi.json").path("/rapidoc"))
    }
}
